#ifndef _WEBSOCKETIMPL_HPP_
#define _WEBSOCKETIMPL_HPP_

#include "jhdefs.hpp"
#include "net/StreamSocketImpl.hpp"
#include "net/SocketAddress.hpp"

#include "math/random.hpp"
using JHCPP::math::CRandom;

#include "stdlib/timestamp.hpp"
using JHCPP::stdlib::CTimeSpan;

NET_NAMESPACE_BEGIN

class CWebSocketImpl : public CStreamSocketImpl
{
public:
	CWebSocketImpl(CStreamSocketImpl* pStreamSocketImpl, bool mustMaskPayload);

	virtual int sendBytes(const void* buffer, int length, int flags);
	virtual int receiveBytes(void* buffer, int length, int flags);

	virtual CSocketImpl* acceptConnection(CSocketAddress& clientAddr);
	virtual void connect(const CSocketAddress& address);
	virtual void connect(const CSocketAddress& address, const CTimeSpan& timeout);
	virtual void connectNB(const CSocketAddress& address);
	virtual void bind(const CSocketAddress& address, bool reuseAddress = false);
	virtual void bind6(const CSocketAddress& address, bool reuseAddress = false, bool ipV6Only = false);
	virtual void listen(int backlog = 64);
	virtual void close();
	virtual void shutdownReceive();
	virtual void shutdownSend();
	virtual void shutdown();
	virtual int sendTo(const void* buffer, int length, const CSocketAddress& address, int flags = 0);
	virtual int receiveFrom(void* buffer, int length, CSocketAddress& address, int flags = 0);
	virtual void sendUrgent(unsigned char data);
	virtual bool secure() const;
	virtual void setSendTimeout(const CTimeSpan& timeout); 
	virtual CTimeSpan getSendTimeout();
	virtual void setReceiveTimeout(const CTimeSpan& timeout);
	virtual CTimeSpan getReceiveTimeout();

	int frameFlags() const;
	bool mustMaskPayload() const;

protected:
	enum
	{
		FRAME_FLAG_MASK   = 0x80,
		MAX_HEADER_LENGTH = 14
	};

	int receiveNBytes(void* buffer, int bytes);
	virtual ~CWebSocketImpl();

private:
	CWebSocketImpl();

	CStreamSocketImpl*	m_pStreamSocketImpl;
	int					m_frameFlags;
	bool				m_mustMaskPayload;
	CRandom				m_rnd;
};


NET_NAMESPACE_END

#endif